package se.sll.itintegration.catalogue.offer.entity;

import java.net.URL;
import java.util.Date;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Fetch;

/**
 *
 * @author khaleddaham
 * @author Jiri Uosukainen
 */
@SuppressWarnings("PMD.UnusedPrivateField")
@Entity
@Data
@Table(name = "offer")
@EqualsAndHashCode(exclude = {"contracts", "productReferences"})
@NamedQueries({
    @NamedQuery(name = OfferEntity.QUERY_FIND_BY_PRODUCT_NAME, query = "SELECT o FROM OfferEntity o WHERE EXISTS(SELECT p FROM o.productReferences p WHERE p.name = :name)")
})
public class OfferEntity {

    public static final String QUERY_FIND_BY_PRODUCT_NAME = "OfferEntity.QUERY_FIND_BY_PRODUCT_NAME";

    @Id
    @GeneratedValue
    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    private Long id;
    @NotNull
    @Column(unique = true, updatable = false)
    private String unitId;
    @NotNull
    private String sourceSystemHSAId;
    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationTime;
    @Temporal(TemporalType.TIMESTAMP)
    private Date updateTime;

    @Fetch(FetchMode.SUBSELECT)
    @ManyToMany(mappedBy = "offers", fetch = FetchType.EAGER)
    private Set<ContractEntity> contracts;

    @Fetch(FetchMode.SUBSELECT)
    @OneToMany(cascade = {CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REMOVE}, mappedBy = "offer", fetch = FetchType.EAGER)
    private Set<ProductReferenceEntity> productReferences;
    
    /**
     * These properties are taken from the big informatiommodel from the project
     * utbud How these attributes are supposed to be modeled and used are not
     * entirely clear, we represent them here in their simplest form.
     */
    private Boolean bookable;
    private String bookableFor; // [KTOV i info-modell]
    private String bookableComment;
    private Boolean remissKrav;
    private String referallRequirement;
    private String referallRequirementComment;
    private URL website;
    private Boolean notificationRequirement;
    private String population; // //[KTOV i info-modell]
    private Boolean forProfessionalActor;
    
    // 0..* name : IIYype
    @Fetch(FetchMode.SUBSELECT)
    @OneToMany(cascade = {CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REMOVE}, mappedBy = "offer", fetch = FetchType.EAGER)
    private Set<IIType> organisation;
    // 0..* name : IIYype
    @Fetch(FetchMode.SUBSELECT)
    @OneToMany(cascade = {CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REMOVE}, mappedBy = "offer", fetch = FetchType.EAGER)
    private Set<IIType> name;
    // 0..* property : CVType
    @Fetch(FetchMode.SUBSELECT)
    @OneToMany(cascade = {CascadeType.DETACH, CascadeType.PERSIST, CascadeType.REMOVE}, mappedBy = "offer", fetch = FetchType.EAGER)
    private Set<CVType> property;
}